home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / DropPrint•USB / ListInDialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  15.3 KB  |  587 lines  |  [TEXT/CWIE]

  1. /*
  2. ListInDialog
  3.  
  4. A snippet that shows how to (uuuhhhhh) put a list in a dialog.
  5.  
  6. I thought we had this one, but I guess not. It's easy, just create the list
  7. right after you create the dialog, then call LUpdate and LClick in a 
  8. dialog filter to respond to user events.
  9.  
  10. Please see the snippet DialogBits for a more comprehensive treatment of
  11. everything you can do in a dialog (well, almost).
  12.  
  13. This is a 680x0 version, built with the Universal Headers.
  14.  
  15. C.K. Haun
  16. April '94
  17. Are you sure we don't already have a snippet like this????
  18. Oh, I rememeber, that was on the //gs
  19.  
  20. */
  21.  
  22. #include <Dialogs.h>
  23. #include <Controls.h>
  24. #include <QuickDraw.h>
  25. #include <Windows.h>
  26. #include <ToolUtils.h>
  27. #include <OSUtils.h>
  28. #include <Menus.h>
  29. #include <Fonts.h>
  30. #include <resources.h>
  31. #include <Sound.h>
  32. #include <Traps.h>
  33. #include <Gestalt.h>
  34. #include <Memory.h>
  35. #include <Scrap.h>
  36. #include <TextEdit.h> 
  37. #include <Lists.h>
  38. #include <Events.h>
  39. #include <string.h>
  40.  
  41. #include "TestPrinterClass.h"
  42. #include "SafeNameRegistry.h"
  43.  
  44. enum  {
  45.     kSampleDialog = 512
  46. };
  47. enum  {
  48.     kModelListItem = 3,
  49.     kNameListItem,
  50.     kStatTextItem1,
  51.     kBlocksizePopupItem,
  52.     kRepeatPopupItem,
  53.     kAlignPopupItem
  54.     
  55. };
  56. enum {
  57.     appleID = 128,
  58.     fileID,
  59.     editID,
  60.     blockID
  61. };
  62.  
  63. enum {
  64.     mApple = 0,
  65.     mFile,
  66.     mEdit,
  67.     mBlocksize,
  68.     MENU_COUNT
  69. };
  70.  
  71. #include "ListInDialog.h"
  72.  
  73. ListHandle    gPrinterList, gModelList;                    /* making the list handle a global */
  74. MenuHandle    menus[MENU_COUNT];
  75. Boolean        done;
  76.  
  77. void 
  78. SetupMenus( void )
  79. {
  80.     short                i;
  81.     MenuHandle            *pMenu;
  82.  
  83.     menus[mApple] = GetMenu(appleID);
  84.     AppendResMenu( menus[mApple], (ResType) 'DRVR');
  85.     InsertMenu( menus[mApple], 0 );
  86.  
  87.     for (pMenu = &menus[1], i = 1; i < MENU_COUNT; i++ ) {
  88.         *pMenu = GetMenu( i + appleID );
  89.         InsertMenu(*pMenu++, 0);
  90.     }
  91.  
  92.     DrawMenuBar();
  93. }
  94.  
  95. ListHandle
  96. MakeDialogList( DialogPtr dlg, int item )
  97. {
  98.  
  99.     // this "rect" defines the data bounds of the list. In this case, a
  100.     // one column list
  101.     Rect tempRect;
  102.     short tempItem;
  103.     Handle tempHandle;
  104.     Rect    listRect2    =  {  0, 0, 0, 1 };
  105.     Cell    cp            =  {  0, 0  };
  106.     // setting it up in the Dialog manager's records, 
  107.     GetDialogItem( dlg, item, &tempItem, &tempHandle, &tempRect);
  108.     
  109.     /* inset the rect by 16, which is the width of the scroll bar that will be attached */
  110.     /* to this list */
  111.     tempRect.right -= 16;
  112.     
  113.     /* set the current port to this dialog */
  114.     SetPort(dlg);
  115.     
  116.     /* create the list */
  117.     
  118.     return LNew(&tempRect,    // in the tempRect bounds
  119.         &listRect2,                // with a sinngle column
  120.         cp,                        // default cell size (a cell of 0,0 says that)
  121.         0,                        // no special LDEF, use the standard one
  122.         dlg,                    // put it in this port
  123.         false,                    // do NOT draw initially
  124.         false,                    // does NOT have a grow box space
  125.         false,                    // does NOT scroll horizontally
  126.         true);                    // DOES have a verticle scroll bar
  127. }
  128.  
  129.  
  130.  
  131. /* Here is the filter that handles any List activity */
  132. pascal Boolean theListFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  133. {
  134.     
  135.     Rect tempR;
  136.     Boolean returnValue = false;    // defaults to me not saying I handled anything
  137.     Boolean theBoolean;
  138.     WindowPtr oldP;
  139.  
  140.     // get the current port, set the port to this dialog
  141.     GetPort(&oldP);
  142.     SetPort(theDialog);
  143.     
  144.     // was this an update event for this dialog?
  145.     if ((theEvent->what == updateEvt) && (theEvent->message == (UInt32)theDialog)) {
  146.         
  147.         FrameOk( theDialog );
  148.         // Update the list.
  149.         LUpdate(theDialog->visRgn, gModelList);
  150.         LUpdate(theDialog->visRgn, gPrinterList);
  151.         
  152.         // get the list rectangle
  153.         // push it outwards one pixel and frame the list
  154.         tempR = (*gModelList)->rView;
  155.         InsetRect(&tempR, -1, -1);
  156.         FrameRect(&tempR);
  157.         
  158.         tempR = (*gPrinterList)->rView;
  159.         InsetRect(&tempR, -1, -1);
  160.         FrameRect(&tempR);
  161.         // NOTE: Do !NOT! return 'true' if you did SOME drawing in response to a dialog update
  162.         // event in your filter!
  163.         // ONLY if you did EVERYTHING should you return 'true', or else you can cause other updating
  164.         // not to occur, which would be Bad
  165.         
  166.     } else {
  167.         // see if this was a mouseDown event
  168.         if (theEvent->what == mouseDown) {
  169.             Point theP;
  170.  
  171.             // we set the port to the dialog on entry to the filter, so a GetMouse will work
  172.             GetMouse(&theP);
  173.             
  174.             // get the list rectangle
  175.             tempR = (*gModelList)->rView;
  176.             
  177.             // add the scroll bar back in for hit testing (remember we took it out earlier)
  178.             tempR.right += 16;
  179.             
  180.             // See if they clicked in our list!
  181.             if (PtInRect(theP, &tempR))
  182.             {
  183.                 theBoolean = LClick(theP, 0, gModelList);
  184.                 // if they double-clicked the list, return 1, as if the OK button had been pressed
  185.                 if (theBoolean)
  186.                     *itemHit = ok;
  187.                 else
  188.                     *itemHit = kModelListItem;
  189.                 
  190.                 // tell the Dialog Manager that we handled this click, it can stop searching for a click-owner
  191.                 returnValue = true;
  192.             }
  193.  
  194.             if ( returnValue != true )
  195.             {
  196.                 // get the list rectangle
  197.                 tempR = (*gPrinterList)->rView;
  198.                 
  199.                 // add the scroll bar back in for hit testing (remember we took it out earlier)
  200.                 tempR.right += 16;
  201.                 
  202.                 // See if they clicked in our list!
  203.                 if (PtInRect(theP, &tempR))
  204.                 {
  205.                     theBoolean = LClick(theP, 0, gPrinterList);
  206.                     // if they double-clicked the list, return 1, as if the OK button had been pressed
  207.                     if (theBoolean)
  208.                         *itemHit = ok;
  209.                     else
  210.                         *itemHit = kNameListItem;
  211.                     
  212.                     // tell the Dialog Manager that we handled this click, it can stop searching for a click-owner
  213.                     returnValue = true;
  214.                 }
  215.             }
  216.             if ( returnValue == true )
  217.             {
  218.                 HiliteOk( theDialog );
  219.             }
  220.         }
  221.     }
  222.    
  223.     // reset the original port
  224.     
  225.     SetPort(oldP);
  226.     
  227.     return(returnValue);
  228. }
  229.  
  230. /*
  231.     Sys7CDEFPopupPrivateDataHdl theMenuData = (Sys7CDEFPopupPrivateDataHdl) (**(ControlHandle)fHItem).contrlData;
  232.  
  233.     return (**theMenuData).mHandle;
  234. */
  235.  
  236. void
  237. HiliteOk( DialogPtr dlg )
  238. {
  239.     //
  240.     //    enable/disable the okay button if we have an item selected in each list
  241.     //
  242.     Cell    cp;
  243.     Boolean enableOk;
  244.     Rect    tempRect;
  245.     short    tempItem;
  246.     Handle    tempHandle;
  247.  
  248.     cp.h = 0;
  249.     cp.v = 0;
  250.     enableOk = LGetSelect( true, &cp, gModelList);
  251.     if ( enableOk )
  252.     {
  253.         cp.h = 0;
  254.         cp.v = 0;
  255.         enableOk = LGetSelect( true, &cp, gPrinterList);
  256.     }
  257.     GetDialogItem( dlg, ok, &tempItem, &tempHandle, &tempRect);
  258.     HiliteControl( (ControlHandle) tempHandle, enableOk? 0: 255 );
  259. }
  260.  
  261. void
  262. FrameOk( DialogPtr dlg )
  263. {
  264.     //
  265.     //    outline the default ok button
  266.     //
  267.     Cell    cp;
  268.     Boolean enableOk;
  269.     Rect    tempRect;
  270.     short    tempItem;
  271.     Handle    tempHandle;
  272.     RGBColor    gray = { 0x3FFF, 0x3FFF, 0x3FFF },
  273.                 black = { 0, 0, 0 };
  274.  
  275.     cp.h = 0;
  276.     cp.v = 0;
  277.     enableOk = LGetSelect( true, &cp, gModelList);
  278.     if ( enableOk )
  279.     {
  280.         cp.h = 0;
  281.         cp.v = 0;
  282.         enableOk = LGetSelect( true, &cp, gPrinterList);
  283.     }
  284.     GetDialogItem( dlg, ok, &tempItem, &tempHandle, &tempRect);
  285.     if ( !enableOk )
  286.         RGBForeColor( &gray );
  287.     InsetRect( &tempRect, -3, -3 );
  288.     PenSize( 3, 3 );
  289.     FrameRoundRect( &tempRect, 16, 16 );
  290.     if ( !enableOk )
  291.         RGBForeColor( &black );
  292.     PenNormal();
  293.  
  294. }
  295.  
  296. void
  297. GetNameFromCell (StringPtr theString, Cell cell, ListHandle hList)
  298. {
  299.     short length;
  300.     
  301.     /*
  302.     The maximum length of the string is the size of a Str255, minus the
  303.     length byte…
  304.     */
  305.     length = sizeof(Str255) - 1;
  306.  
  307.     LGetCell((StringPtr)(theString + 1), &length, cell, hList);
  308.     
  309.     /*
  310.     Set the length byte.
  311.     */
  312.     *theString = (unsigned char) length;
  313. }
  314.  
  315. int
  316. GetDialogPopupValue( DialogPtr dlg, int item )
  317. {
  318.     Rect    tempRect;
  319.     short    tempItem;
  320.     Handle    tempHandle;
  321.  
  322.     GetDialogItem( dlg, item, &tempItem, &tempHandle, &tempRect);
  323.     return GetControlValue( (ControlHandle) tempHandle);
  324. }
  325.  
  326. void
  327. SetDialogPopupValue( DialogPtr dlg, int item, int value )
  328. {
  329.     Rect    tempRect;
  330.     short    tempItem;
  331.     Handle    tempHandle;
  332.  
  333.     GetDialogItem( dlg, item, &tempItem, &tempHandle, &tempRect);
  334.  
  335.     SetControlValue( (ControlHandle) tempHandle, value );
  336. }
  337.  
  338. int
  339. ChoosePrinter( char *name, long *blocksize, int *repeats)
  340. //ChoosePrinter( char *name, long *blocksize, int *repeats, int *align )
  341. {
  342.     char        model[255];
  343.     short        length;
  344.     Cell        cp =  {   0, 0 };         // cell to initialize with
  345.     DialogPtr    myDialog = nil; // the dialog we're using
  346.     short        hitItem = 0;    // hitItem for ModalDialog call
  347.  
  348.     static ModalFilterUPP modalFilterUPP;
  349.     
  350.     modalFilterUPP = NewModalFilterProc(theListFilter);
  351.     /* get our dialog. It is created HIDDEN, and shown after I set the */
  352.     /* user item that will hold the list */
  353.  
  354.     myDialog = GetNewDialog(kSampleDialog, nil, (WindowPtr)-1);
  355.     
  356.     // list all the known printer models
  357.     gModelList = MakeDialogList( myDialog, kModelListItem );
  358.     gPrinterList = MakeDialogList( myDialog, kNameListItem );
  359.    
  360.     SetUpList( gModelList, "");         // list all the known printer of the first model
  361.     SetDialogPopupValue( myDialog, kBlocksizePopupItem, 6 );    //    512 byte default blocksize
  362.     SetDialogPopupValue( myDialog, kRepeatPopupItem, 1 );        //    only send file down once
  363.     
  364.     cp.h = 0;
  365.     cp.v = 0;
  366.     length = sizeof(model);
  367.       LGetCell( model, &length, cp, gModelList);
  368.       if ( length > 0 )
  369.       {
  370.           LSetSelect( true, cp, gModelList);        // select the first model
  371.  
  372.         model[ length ] = 0;    // null terminate c-string
  373.            SetUpList( gPrinterList, model );
  374.         length = sizeof(model);
  375.         cp.h = 0;
  376.         cp.v = 0;
  377.           LGetCell( model, &length, cp, gPrinterList);
  378.           if ( length > 0 )
  379.           {
  380.               LSetSelect( true, cp, gPrinterList);    // select the first printer name
  381.            }
  382.     }
  383.     // turn drawing on after the list has been filled
  384.     LSetDrawingMode(true, gModelList);
  385.     LSetDrawingMode(true, gPrinterList);
  386.     HiliteOk( myDialog );    // enable/disable ok button
  387.  
  388.     // show the dialog
  389.     ShowWindow((WindowPtr)myDialog);
  390.     
  391.     /* draw it once */
  392.     DrawDialog(myDialog);
  393.     
  394.     // loop until ModalDialog is done
  395.     do {
  396.         // we have to use a ModalDialog filter, since ModalDialog doesn't
  397.         // automatically handle lists
  398.         ModalDialog(modalFilterUPP, &hitItem);
  399.         
  400.         // switch off what item was hit
  401.         switch (hitItem) {
  402.         case kModelListItem:    
  403.             //
  404.             //    rebuild the list of specific printers
  405.              //
  406.             cp.h = 0;
  407.             cp.v = 0;
  408.             if ( LGetSelect( true, &cp, gModelList) )
  409.             {
  410.                 length = sizeof(model);
  411.                   LGetCell( model, &length, cp, gModelList);
  412.                   model[ length ] = 0;
  413.  
  414.                 // create a new list of printer names
  415.                 LDispose( gPrinterList );
  416.                    gPrinterList = MakeDialogList( myDialog, kNameListItem );
  417.                   SetUpList( gPrinterList, model );
  418.                 cp.h = 0;
  419.                 cp.v = 0;
  420.                   LGetCell( model, &length, cp, gPrinterList);
  421.                   if ( length > 0 )
  422.                   {
  423.                       LSetSelect( true, cp, gPrinterList);    // select the first printer name
  424.                    }
  425.                   LSetDrawingMode(true, gPrinterList);
  426.                   LUpdate( myDialog->visRgn, gPrinterList );
  427.               }
  428.               break;
  429.         default:
  430.             break;
  431.             
  432.         }
  433.         // wait for an OK or Cancel
  434.     }  while (hitItem != ok && hitItem != cancel);
  435.     
  436.     if ( hitItem == ok )
  437.     {
  438.         //
  439.         //    save a reference to the requested printer
  440.         //
  441.         cp.h = 0;
  442.         cp.v = 0;
  443.         if ( LGetSelect( true, &cp, gModelList) )
  444.         {
  445.             length = sizeof(model);
  446.               LGetCell( model, &length, cp, gPrinterList);
  447.               model[ length ] = 0;
  448.             strcpy( name, "Devices:device-tree:PRINTER:" );
  449.             strcat( name, model );
  450.  
  451.             cp.h = 0;
  452.             cp.v = 0;
  453.             if ( LGetSelect( true, &cp, gPrinterList) > 0 )
  454.             {
  455.                 length = sizeof(model);
  456.                   LGetCell( model, &length, cp, gPrinterList);
  457.                   model[ length ] = 0;
  458.                 strcat( name, ":" );
  459.                 strcat( name, model );
  460.             }
  461.         }
  462.         //
  463.         //    get the current blocksize
  464.         //
  465.         *blocksize = 1L<< (GetDialogPopupValue( myDialog, kBlocksizePopupItem ) - 1);
  466.         //
  467.         //    get the number of times to send the file
  468.         //
  469.         switch( GetDialogPopupValue( myDialog, kRepeatPopupItem ) )
  470.         {
  471.         case 2:    *repeats =  2; break;
  472.         case 3:    *repeats =  5; break;
  473.         case 4:    *repeats = 10; break;
  474.         case 5:    *repeats = 20; break;
  475.         case 6:    *repeats = 30; break;
  476.         case 7:    *repeats = 50; break;
  477.         case 8:    *repeats =100; break;
  478.         default:
  479.         case 1:    *repeats =  1; break;
  480.         }
  481.          switch( GetDialogPopupValue( myDialog, kAlignPopupItem ) )
  482.         {
  483.         case 1:    
  484.         case 2:
  485.         case 3:
  486.         case 4:
  487.         case 5:
  488.         case 6:
  489.         default:
  490.         break;
  491.         }
  492.    }
  493.    // don't do anything in this sample
  494.    LDispose( gModelList );
  495.    LDispose( gPrinterList  );
  496.     DisposeDialog(myDialog);
  497.     return hitItem;
  498. }
  499.  
  500. /*-----------------------------------------------------------------------------*
  501.  
  502.     SearchForUSBPrinters
  503.     
  504.     Desc:        Searches thru a printer model entry in the name registry
  505.                 looking for a model's printers. When one is found a call is 
  506.                 issued to the clients callback routine for further processing
  507.  
  508.     In:            - A pstring full path in the name registry of a printer model
  509.                 - A callback routine which gets called when a printer is found
  510.                 - A ptr to user data
  511.                 
  512.     Out:        None
  513.     
  514.     History:
  515.     
  516.     17 Apr 98    oja        modified to use list manager instead of Chooser
  517.     24 Feb 98    gp        Created
  518.     
  519.  *-----------------------------------------------------------------------------*/
  520. void    
  521. SetUpList( ListHandle theList, char *modelPath )
  522. {
  523.  
  524.     RegEntryID        theModelEntry;        // the model node supported by the driver
  525.     RegEntryID        aPrinterEntry;        // a printer node in the name registry
  526.     RegEntryIterationOp iterOp;            // name registry iterator op code
  527.     RegEntryIter    printerIterator;    // used to iterate child nodes of printer model
  528.     Boolean            donePrinters    = false;    // NameRegistry param tell when we're done
  529.     OSStatus        err             = noErr;    // error from name registry calls
  530.     char            path[256];
  531.     short             listCount = 0;
  532.     Cell            cp;
  533.  
  534.     // name registry only deals with c strings
  535.     strcpy( path, "Devices:device-tree:PRINTER" );
  536.     if ( modelPath[0] != 0 )
  537.     {
  538.         strcat( path, ":" );
  539.         strcat( path, modelPath );
  540.     }
  541.     
  542.     // look up the node for the printer model requested
  543.     err = SafeRegistryEntryIDInit(&theModelEntry);
  544.     if( err == noErr ) 
  545.         err = SafeRegistryCStrEntryLookup( nil, path, &theModelEntry );
  546.     if( err == noErr ) 
  547.     {
  548.         // create an iterator to look at the child nodes for our printer model entry
  549.         iterOp = kRegIterChildren;
  550.  
  551.         err = SafeRegistryEntryIterateCreate( &printerIterator );
  552.         err = SafeRegistryEntryIterateSet(&printerIterator, &theModelEntry);
  553.         
  554.         if( err == noErr )
  555.         {
  556.             // look for a model's connected printers
  557.             do
  558.             {
  559.                 Str255                    nodeName;            // the name of the printer
  560.                 RegPropertyValueSize    nameSize;    // size of name buffer
  561.  
  562.                 err = SafeRegistryEntryIterate( &printerIterator, iterOp, &aPrinterEntry, &donePrinters );
  563.                 // grab name of printer in name registyr
  564.                 nameSize = sizeof( nodeName );
  565.                 if( !donePrinters && err == noErr )
  566.                     err = SafeRegistryPropertyGet( &aPrinterEntry, "name", &nodeName, &nameSize );
  567.                 if( !donePrinters && err == noErr )
  568.                 {
  569.                     // add the printer to the list
  570.                     listCount = LAddRow(1, listCount + 1, theList);
  571.                     cp.h = 0;
  572.                     cp.v = listCount;
  573.                     LAddToCell(&nodeName, nameSize-1, cp, theList);
  574.                 }
  575.                 iterOp = kRegIterContinue;
  576.             } while( !donePrinters && err == noErr );
  577.             // end while for printers
  578.         }
  579.         SafeRegistryEntryIterateDispose(&printerIterator);
  580.     }
  581.  
  582.     SafeRegistryEntryIDDispose( &theModelEntry );
  583.  
  584. }
  585.  
  586. // eof
  587.